home *** CD-ROM | disk | FTP | other *** search
/ Inter.Net 55-1 / Inter.Net 55-1.iso / CBuilder / Setup / BCB / data.z / perfgrap.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-09  |  12.1 KB  |  459 lines

  1. //---------------------------------------------------------------------------
  2. // Borland C++Builder
  3. // Copyright (c) 1987, 1998 Borland International Inc.  All Rights Reserved.
  4. //---------------------------------------------------------------------------
  5. //---------------------------------------------------------------------------
  6. //#include <vcl.h>
  7. #pragma hdrstop
  8.  
  9. #pragma unit
  10. #pragma package(smart_init);
  11. #pragma resource "*.res"
  12.  
  13. #include "PerfGrap.h"
  14. #include "samp.h"
  15. //---------------------------------------------------------------------------
  16. static inline TPerformanceGraph *ValidCtrCheck()
  17. {
  18.     return new TPerformanceGraph(NULL);
  19. }
  20. //---------------------------------------------------------------------------
  21. __fastcall TPerformanceGraph::TPerformanceGraph(TComponent* Owner)
  22.     : TGraphicControl(Owner)
  23. {
  24.     ControlStyle << csFramed << csOpaque;
  25.  
  26.     // default values
  27.     FKind       = pgLine;
  28.     FForeColor = clGreen;
  29.     FBackColor = clBlack;
  30.     FGridSize  = 15;
  31.     FStepSize  = 3;
  32.     FGradient  = 100;
  33.     FGridlines = true;
  34.     FPenWidth  = 2;
  35.     FScale       = 1000;
  36.     Width       = 100;
  37.     Height       = 100;
  38.  
  39.     Canvas->Pen->Width = FPenWidth;
  40.     
  41.     // create objects used by class.  Bands is incremented by two in
  42.     // order to have one TDataPoints object for the oldest,
  43.     // non-visible data (so that PaintLine can do its job correctly),
  44.     // and one for the current "in-progress" data, which has not been
  45.     // displayed yet.
  46.     Allocated  = Bands + 2;
  47.     History       = new TDataPoints[Allocated];
  48.     BeginY       = 1;
  49.     CurrentY   = 0;
  50.  
  51.     Hidden     = 0;
  52.     SaveArea   = new Graphics::TBitmap;
  53.     Occupied   = false;
  54.  
  55.     // simulate a history of empty data
  56.     for    (int i = 0; i < Allocated; i++)
  57.         History[i].used = 0;
  58.  
  59.     // initialize the save area used for painting
  60.     Initialize(GridSize - 1);
  61. }
  62. //---------------------------------------------------------------------------
  63. __fastcall TPerformanceGraph::~TPerformanceGraph()
  64. {
  65.     delete SaveArea;
  66.     delete[] History;
  67. }
  68. //---------------------------------------------------------------------------
  69. void __fastcall TPerformanceGraph::Initialize(Longint Index)
  70. {
  71.     // define the memory area for the bitmap
  72.     SaveArea->Width      = Width;
  73.     SaveArea->Height  = Height;
  74.     
  75.     // create a rectangle which represents the size of SaveArea
  76.     LayoutRect.Left      = 0;
  77.     LayoutRect.Top      = 0;
  78.     LayoutRect.Right  = SaveArea->Width;
  79.     LayoutRect.Bottom = SaveArea->Height;
  80.  
  81.     // paint the background
  82.     SaveArea->Canvas->Brush->Color = BackColor;
  83.     SaveArea->Canvas->FillRect(LayoutRect);
  84.  
  85.     // draw the grid lines
  86.     if    (Gridlines)
  87.     {
  88.         SaveArea->Canvas->Pen->Color = ForeColor;
  89.  
  90.         // draw the vertical grid lines
  91.         TPoint p;
  92.         p.x = LayoutRect.Left;
  93.         for    (int i = GridSize; i < LayoutRect.Bottom; i += GridSize)
  94.         {
  95.             p.y = i;
  96.             SaveArea->Canvas->PenPos = p;
  97.             SaveArea->Canvas->LineTo(LayoutRect.Right, i);
  98.         }
  99.  
  100.         // draw the horizontal grid lines
  101.         p.y = 0;
  102.         int vert;
  103.         for    (vert = Index; vert < LayoutRect.Right; vert += GridSize)
  104.         {
  105.             p.x = vert;
  106.             SaveArea->Canvas->PenPos = p;
  107.             SaveArea->Canvas->LineTo(vert, LayoutRect.Bottom);
  108.         }
  109.         Hidden = vert - LayoutRect.Right;
  110.     }
  111.  
  112.     // cache rectangles used for updating graph display
  113.     SourceRect = DestRect = OpenBand = LayoutRect;
  114.     SourceRect.Left = StepSize;
  115.     DestRect.Right -= StepSize;
  116.     OpenBand.Left = LayoutRect.Right - StepSize;
  117. }
  118. //---------------------------------------------------------------------------
  119. void __fastcall TPerformanceGraph::Paint()
  120. {
  121.     // if the shape of the graph has changed at all, redraw it
  122.     if    (Height != SaveArea->Height || Width != SaveArea->Width)
  123.     {
  124.         if    (Width != SaveArea->Width)
  125.             ReallocHistory();
  126.         Replay();
  127.     }
  128.  
  129.     // copy the cached image to the control
  130.     Canvas->CopyMode = cmSrcCopy;
  131.     Canvas->Draw(0, 0, SaveArea);
  132. }
  133. //---------------------------------------------------------------------------
  134. void __fastcall TPerformanceGraph::SetGraphKind(TGraphKind Value)
  135. {
  136.     if    (Value != FKind)
  137.     {
  138.         FKind = Value;
  139.         Replay();
  140.     }
  141. }
  142.  
  143. void __fastcall TPerformanceGraph::SetForeColor(TColor Value)
  144. {
  145.     if    (Value != FForeColor)
  146.     {
  147.         FForeColor = Value;
  148.         Replay();
  149.     }
  150. }
  151.  
  152. void __fastcall TPerformanceGraph::SetBackColor(TColor Value)
  153. {
  154.     if    (Value != FBackColor)
  155.     {
  156.         FBackColor = Value;
  157.         Replay();
  158.     }
  159. }
  160.  
  161. void __fastcall TPerformanceGraph::SetGridSize(Longint Value)
  162. {
  163.     if    (Value != FGridSize)
  164.     {
  165.         if    (Value < 2)
  166.             Value = 2;
  167.         FGridSize = Value;
  168.         Replay();
  169.     }
  170. }
  171.  
  172. void __fastcall TPerformanceGraph::SetStepSize(Longint Value)
  173. {
  174.     if    (Value != FStepSize)
  175.     {
  176.         if    (Value < 1)
  177.             Value = 1;
  178.         FStepSize = Value;
  179.         ReallocHistory();
  180.         Replay();
  181.     }
  182. }
  183.  
  184. void __fastcall TPerformanceGraph::SetScale(Longint Value)
  185. {
  186.     if    (Value != FScale)
  187.     {
  188.         FScale = RoundUp(Value, Gradient);
  189.  
  190.         if    (OnScaleChange)
  191.             OnScaleChange(this);
  192.  
  193.         Replay();
  194.     }
  195. }
  196.  
  197. void __fastcall TPerformanceGraph::SetGradient(Longint Value)
  198. {
  199.     if    (Value != FGradient)
  200.     {
  201.         FGradient = Value;
  202.         Replay();
  203.     }
  204. }
  205.  
  206. void __fastcall TPerformanceGraph::SetGridlines(Boolean Value)
  207. {
  208.     if    (Value != FGridlines)
  209.     {
  210.         FGridlines = Value;
  211.         Replay();
  212.     }
  213. }
  214.  
  215. void __fastcall TPerformanceGraph::SetPenWidth(Longint Value)
  216. {
  217.     if    (Value != FPenWidth)
  218.     {
  219.         FPenWidth = Value;
  220.         Canvas->Pen->Width = FPenWidth;
  221.         Replay();
  222.     }
  223. }
  224. //---------------------------------------------------------------------------
  225. void __fastcall TPerformanceGraph::PaintBar(TColor color, Longint base,
  226.     Longint amount)
  227. {
  228.     if    (! amount)
  229.         return;
  230.  
  231.     // compute the size and shape of the bar, relative to the graph
  232.     double range = double(LayoutRect.Bottom - LayoutRect.Top);
  233.     long pixels  = long(range * (double(amount) / double(Scale)));
  234.     long offset  = long(range * (double(base) / double(Scale)));
  235.  
  236.     if    (! pixels)
  237.         return;
  238.  
  239.     // define the exact area of the bar
  240.     TRect area;
  241.     area.Left   = OpenBand.Left;
  242.     area.Right  = OpenBand.Right;
  243.     area.Top    = LayoutRect.Bottom - offset - pixels - 1;
  244.     area.Bottom = LayoutRect.Bottom - offset;
  245.  
  246.     // paint the bar using the color specified
  247.     SaveArea->Canvas->Brush->Color = color;
  248.     SaveArea->Canvas->FillRect(area);
  249. }
  250. //---------------------------------------------------------------------------
  251. void __fastcall TPerformanceGraph::PaintLine(TColor color, Longint lastAmount,
  252.     Longint amount)
  253. {
  254.     // compute the size and shape of the lines, relative to the graph
  255.     double percent = double(amount) / double(Scale);
  256.     long pixels = long(double(LayoutRect.Bottom - LayoutRect.Top) * percent);
  257.     percent = double(lastAmount) / double(Scale);
  258.     long lpixels = long(double(LayoutRect.Bottom - LayoutRect.Top) * percent);
  259.  
  260.     // define the left point of the line
  261.     TPoint left;
  262.     left.x = OpenBand.Left;
  263.     left.y = LayoutRect.Bottom - lpixels;
  264.  
  265.     // draw the line using the color specified
  266.     SaveArea->Canvas->Pen->Color = color;
  267.     SaveArea->Canvas->PenPos = left;
  268.     SaveArea->Canvas->LineTo(OpenBand.Right, LayoutRect.Bottom - pixels);
  269. }
  270. //---------------------------------------------------------------------------
  271. void __fastcall TPerformanceGraph::DataPoint(TColor color, Longint value)
  272. {
  273.     // check to see if the internal limit has been exceeded
  274.     if    (History[CurrentY].used >= MAXLINES)
  275.         throw ERangeError(LoadStr(Exceed_RC));
  276.  
  277.     // save the data point for display on the next call to Update
  278.     History[CurrentY].color[History[CurrentY].used] = color;
  279.     History[CurrentY].value[History[CurrentY].used] = value;
  280.     History[CurrentY].used++;
  281. }
  282. //---------------------------------------------------------------------------
  283. void __fastcall TPerformanceGraph::ScrollGraph()
  284. {
  285.     // cycle the grid over, repainting the hash lines so that they
  286.     // appear unbroken
  287.     SaveArea->Canvas->CopyRect(DestRect, SaveArea->Canvas, SourceRect);
  288.     SaveArea->Canvas->Brush->Color = BackColor;
  289.     SaveArea->Canvas->FillRect(OpenBand);
  290.  
  291.     // if the user does not want gridlines, skip this step
  292.     if    (! Gridlines)
  293.         return;
  294.  
  295.     SaveArea->Canvas->Pen->Color = ForeColor;
  296.  
  297.     // draw the horizontal grid lines
  298.     TPoint p;
  299.     p.x = OpenBand.Left;
  300.     for    (int i = GridSize; i < OpenBand.Bottom; i += GridSize)
  301.     {
  302.         p.y = i;
  303.         SaveArea->Canvas->PenPos = p;
  304.         SaveArea->Canvas->LineTo(OpenBand.Right, i);
  305.     }
  306.  
  307.     // draw a vertical grid line, if we should
  308.     Hidden -= StepSize;
  309.     if    (Hidden < 0)
  310.     {
  311.         TPoint p;
  312.         p.x = LayoutRect.Right + Hidden;
  313.         p.y = LayoutRect.Top;
  314.         SaveArea->Canvas->PenPos = p;
  315.         SaveArea->Canvas->LineTo(p.x, LayoutRect.Bottom);
  316.         Hidden += GridSize;
  317.     }
  318. }
  319. //---------------------------------------------------------------------------
  320. void __fastcall TPerformanceGraph::DisplayPoints(Longint Index)
  321. {
  322.     long    base = 0;
  323.  
  324.     // display the data points that were added by the user
  325.     for    (int i = 0; i < History[Index].used; i++)
  326.     {
  327.         if    (History[Index].value[i])
  328.         {
  329.             TColor    Color = History[Index].color[i];
  330.             
  331.             switch    (Kind)
  332.             {
  333.             case    pgBar: 
  334.                 PaintBar(Color, base, History[Index].value[i] - base);
  335.                 break;
  336.  
  337.             case    pgLine: 
  338.             {
  339.                 TDataPoints& last = History[LastY(Index)];
  340.                 Longint LastValue = 0;
  341.  
  342.                 for    (int j = 0; j < last.used; j++)
  343.                 {
  344.                     if    (last.color[j] == Color)
  345.                     {
  346.                         LastValue = last.value[j];
  347.                         break;
  348.                     }
  349.                 }
  350.                         
  351.                 PaintLine(Color, LastValue, History[Index].value[i]);
  352.                 break;
  353.             }
  354.             }
  355.             base = History[Index].value[i];
  356.         }
  357.     }
  358. }
  359. //---------------------------------------------------------------------------
  360. void __fastcall TPerformanceGraph::ReallocHistory()
  361. {
  362.     // allocate the new history list
  363.     Longint NewCount = Bands + 2;
  364.     TDataPoints    *NewHistory = new TDataPoints[NewCount];
  365.     for    (int i = 0; i < NewCount; i++)
  366.         NewHistory[i].used = 0;
  367.  
  368.     // if the new history is smaller than the old one, then ignore the
  369.     // first X elements in the old one, where X is how much smaller
  370.     // the new history is
  371.     int i = FirstY();
  372.     if    (NewCount < Allocated)
  373.         for    (int j = 0; j < (Allocated - NewCount); j++)
  374.             i = NextY(i);
  375.     
  376.     // copy over the elements.  Because of the code just above, we
  377.     // know that the old history will always be equal to or smaller in
  378.     // size than the new history
  379.     int x = 0;
  380.     for    (; i != LIST_END; i = NextY(i))
  381.         NewHistory[x++] = History[i];
  382.  
  383.     // delete the old history list.  We are now using the new one
  384.     delete[] History;
  385.     History = NewHistory;
  386.  
  387.     // reset the list pointers
  388.     Allocated = NewCount;
  389.     CurrentY  = x - 1;
  390.     BeginY    = 0;
  391. }
  392. //---------------------------------------------------------------------------
  393. void __fastcall TPerformanceGraph::Update()
  394. {
  395.     // scroll the graph to the left by StepSize
  396.     ScrollGraph();
  397.  
  398.     // since the graph has scrolled, drop old data
  399.     ShiftY();
  400.  
  401.     // determine if the scale should be changed
  402.     Longint largest = 0;
  403.     for    (int y = FirstY(); y != LIST_END; y = NextY(y))
  404.         for    (int x = 0; x < History[y].used; x++) 
  405.             if    (History[y].value[x] > largest)
  406.                 largest = History[y].value[x];
  407.  
  408.     largest = RoundUp(largest, Gradient);
  409.  
  410.     // if the scale needs to be changed...
  411.     if    (largest != Scale)
  412.         Scale = largest;                    // causes call to Replay()
  413.     else
  414.     {
  415.         // otherwise just update the display
  416.         DisplayPoints(LastY(CurrentY));
  417.         Refresh();
  418.     }
  419. }
  420. //---------------------------------------------------------------------------
  421. void __fastcall TPerformanceGraph::Replay()
  422. {
  423.     // repaint the graph background, preserving vertical positions
  424.     Longint Span = Width + Hidden;
  425.     Longint Index = Span - ((Span / GridSize) * GridSize);
  426.     Initialize(Index);
  427.  
  428.     // save the 'open band', which is where data gets painted
  429.     TRect SaveBand = OpenBand;
  430.  
  431.     // begin at vertical column 'left'
  432.     int left = Width % Bands;
  433.  
  434.     // repaint all of the historical items
  435.     for    (int i = NextY(FirstY()); i != LIST_END; i = NextY(i))
  436.     {
  437.         OpenBand.Left = left;
  438.         left += StepSize;
  439.         OpenBand.Right = left;
  440.  
  441.         // draw the historical item
  442.         DisplayPoints(i);
  443.     }
  444.     Refresh();
  445.  
  446.     // restore the open band
  447.     OpenBand = SaveBand;
  448. }
  449. //---------------------------------------------------------------------------
  450. namespace Perfgrap
  451. {
  452.     void PACKAGE __fastcall Register()
  453.     {
  454.         TComponentClass classes[1] = {__classid(TPerformanceGraph)};
  455.         RegisterComponents(LoadStr(Tab_101), classes, 0);
  456.     }
  457. }
  458. //---------------------------------------------------------------------------
  459.